﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<assert.h>


//计算结构体的⼤⼩   
// 结构体内存对⻬
//struct S
//{
//	char c1;
//	int i;
//	char c2;
//};
//int main()
//{
//	struct S s = { 0 };
//	printf("%zd\n", sizeof(s));//12
//
//	return 0;
//}

//⾸先得掌握结构体的对⻬规则：
//1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
//2.其他成员变量要对⻬到某个数字（对⻬数）的整数倍的地址处。
//对⻬数 = 编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。
//-VS 中默认的值为 8 
// -Linux中gcc没有默认对⻬数，对⻬数就是成员⾃⾝的⼤⼩
//3.结构体总⼤⼩为最⼤对⻬数（结构体中每个成员变量都有⼀个对⻬数，所有对⻬数中最⼤的）的
//整数倍。
//4.如果嵌套了结构体的情况，嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处，结构
//体的整体⼤⼩就是所有最⼤对⻬数（含嵌套结构体中成员的对⻬数）的整数倍。


//练习1 
//struct S1
//{
//	char c1;
//	int i;
//	char c2;
//};
//printf("%d\n", sizeof(struct S1));//12
////练习2 
//struct S2
//{
//	char c1;
//	char c2;
//	int i;
//};
//printf("%d\n", sizeof(struct S2));//8
////练习3 
//struct S3
//{
//	double d;
//	char c;
//	int i;
//};
//printf("%d\n", sizeof(struct S3));//16
////练习4-结构体嵌套问题 
//struct S4
//{
//	char c1;
//	struct S3 s3;
//	double d;
//};
//printf("%d\n", sizeof(struct S4));//32



//为什么存在内存对⻬ ? 
//⼤部分的参考资料都是这样说的：
//1. 平台原因(移植原因)：
//不是所有的硬件平台都能访问任意地址上的任意数据的；某些硬件平台只能在某些地址处取某些特定
//类型的数据，否则抛出硬件异常。
//2. 性能原因：
//数据结构(尤其是栈)应该尽可能地在⾃然边界上对⻬。原因在于，为了访问未对⻬的内存，处理器需要
//作两次内存访问；⽽对⻬的内存访问仅需要⼀次访问。假设⼀个处理器总是从内存中取8个字节，则地
//址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数，那么就可以
//⽤⼀个内存操作来读或者写值了。否则，我们可能需要执⾏两次内存访问，因为对象可能被分放在两
//个8字节内存块中。
//总体来说：结构体的内存对⻬是拿空间来换取时间的做法。
//让占⽤空间⼩的成员尽量集中在⼀起
//例如： 
//struct S1
//{
//	char c1;
//	int i;
//	char c2;
//};
//struct S2
//{
//	char c1;
//	char c2;
//	int i;
//};


//#pragma pack(1)//设置默认对⻬数为1 
//struct S
//{
//	char c1;
//	int i;
//	char c2;
//};
//#pragma pack()//取消设置的对⻬数，还原为默认 
//int main()
//{
//	//输出的结果是什么？ 
//	printf("%zd\n", sizeof(struct S));//6
//	return 0;
//}
//struct S
//{
//	int arr[1000];
//	int n;
//	double d;
//};
//void print(struct S tmp)
//{
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		printf("%d ", tmp.arr[i]);
//	}
//	printf("%d ", tmp.n);
//	printf("%lf\n ", tmp.d);
//}
//int main()
//{
//	struct S s = { {1,2,3,4,5},100,3.14 };
//	print(s);
//	return 0;
//}
// 
// 
struct S
{
	int data[1000];
	int num;
};
struct S s = { {1,2,3,4}, 1000 };
//结构体传参 
void print1(struct S s)
{
	printf("%d\n", s.num);
}
//结构体地址传参 
void print2(struct S* ps)
{
	printf("%d\n", ps->num);
}
int main()
{
	print1(s); //传结构体 
	print2(&s); //传地址 
	return 0;
}

//函数传参的时候，参数是需要压栈，会有时间和空间上的系统开销。
//如果传递⼀个结构体对象的时候，结构体过⼤，参数压栈的的系统开销⽐较⼤，所以会导致性能的下降。
//结构体传参的时候，要传结构体的地址。




















































